#ifndef __MY_LOG_HPP__
#define __MY_LOG_HPP__

#include <iostream>
#include <string>
#include <ctime>

namespace qihai
{
    enum
    {
        DEBUG,    // 测试
        INFO,     // 常规-正常信息
        WARNING,  // 警告 
        ERROR,    // 错误
        FATAL     // 致命的
    };

    // 固定全局变量
    // static const uint8_t LOGHEADLEN= 64;  // log头部的固定大小 - 方便扩容
    static bool LOG_ISDAEMON = false;  // 全局的变量 - 表示当前是否是守护进程模式 是的化对打印内容进行修改

#ifndef QIHAI_DEBUG  // 没有定义debug模式，需要排除debug的输出
    // 定义一个全局的空流对象
    static std::ostream nullstream(nullptr);
#endif

    // 控制Linux显示等级颜色
    inline static std::string LevelColour(uint8_t level)
    {
        std::string levelString ="\033[";
        if (LOG_ISDAEMON) levelString = "";
        switch (level)
        {
        case DEBUG:
            if (LOG_ISDAEMON) levelString += "DEBUG";
            else levelString += "34mDEBUG\033[0m";  // 33m 为蓝色
            break;
        case INFO:
            if (LOG_ISDAEMON) levelString += "INFO";
            else levelString += "32mINFO\033[0m";   // 32m 为绿色
            break;
        case WARNING:
            if (LOG_ISDAEMON) levelString += "WARNING";
            else levelString += "33mWARNING\033[0m";   // 33m 为黄色
            break;
        case ERROR:
            if (LOG_ISDAEMON) levelString += "ERROR";
            else levelString += "31mERROR\033[0m";   // 31m 为红色
            break;
        case FATAL:
            if (LOG_ISDAEMON) levelString += "FATAL";
            else levelString += "31mFATAL\033[0m";   // 31m 为红色
            break;
        default:
            if (LOG_ISDAEMON) levelString += "null";
            else levelString += "37mnull\033[0m";  // 未知 37m为白色
            break;
        }

        return levelString;
    }

    // 开放输入日志函数
    // "[LEVEL][xxxx-xx-xx xx:xx:xx filename line] "
    // 如果想让debug等级日志输出编译需要加上宏选项-DQIHAI_DEBUG即可
    // 注意如果想设置守护进程打印到本地log文件，后面需要加上std::endl或者std::flush 才会立即刷新缓冲区,\n不行.
    inline std::ostream& Log(uint8_t level, const std::string& fileName, int line)
    {
#ifndef QIHAI_DEBUG  // 没有定义debug的宏，排除debug输出
        if (level == DEBUG)
            return nullstream;
#endif

        std::string log;
        // log.resize(LOGHEADLEN, 0);  // 注意这样可能存在乱码
        
        // LEVEL
        log += '[';
        log += LevelColour(level);
        log += ']';

        // TIME
        time_t timestamp = time(nullptr);  // 获取时间戳
        struct tm* timeInfo = localtime(&timestamp);  // 将时间戳转换为GMT时间，填充到结构体中去 localtime 是当前时区的时间
        log += '[';
        log += std::to_string(timeInfo->tm_year + 1900) + '-' + std::to_string(timeInfo->tm_mon + 1) + '-' + std::to_string(timeInfo->tm_mday) + ' ' + \
               std::to_string(timeInfo->tm_hour) + ':' + std::to_string(timeInfo->tm_min) + ':' + std::to_string(timeInfo->tm_sec) + ' ';
        
        // FILE
        log += fileName + ' ';
        log += std::to_string(line);
        log += "] ";

        return std::cout << log;
    }

    // 开放输入日志函数
    // "[LEVEL][xxxx-xx-xx xx:xx:xx filename line] "
    // 如果想让debug等级日志输出编译需要加上宏选项-DQIHAI_DEBUG即可
    // 注意如果想设置守护进程打印到本地log文件，后面需要加上std::endl或者std::flush 才会立即刷新缓冲区,\n不行.
    // 存在全局变量LOG_ISDAEMON，设置其为true不会打印等级颜色
    #define LOG(level) Log(level, __FILE__, __LINE__)
}

#endif